package cn.jhz.learn.blog.component.shiro.filter;

import cn.jhz.learn.blog.component.GLOBAL;
import cn.jhz.learn.blog.util.JwtUtil;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.web.filter.authc.AnonymousFilter;
import org.apache.shiro.web.util.WebUtils;
import org.jose4j.jwt.MalformedClaimException;
import org.jose4j.jwt.consumer.InvalidJwtException;
import org.jose4j.lang.JoseException;
import org.springframework.http.HttpStatus;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

public class JwtAnonymousFilter extends AnonymousFilter {

    @Override
    protected boolean onPreHandle(ServletRequest request, ServletResponse response, Object mappedValue) {
        HttpServletRequest servletRequest = (HttpServletRequest) request;
        HttpServletResponse servletResponse = (HttpServletResponse) response;
        String jwt = servletRequest.getHeader(GLOBAL.TOKEN_INFO.AUTH_HEADER);
        if(StringUtils.isNotBlank(jwt)){
            try {
                JwtUtil.getInstance().validated(jwt, JwtUtil.getInstance().parseJWT(jwt).getAudience());

                servletResponse.setHeader(GLOBAL.TOKEN_INFO.AUTH_HEADER, JwtUtil.getInstance().reflashJwsToken(jwt));
                servletResponse.setHeader(GLOBAL.HEADER_INFO.ACCESS_CONTROL_EXPOSE_HEADERS, GLOBAL.TOKEN_INFO.AUTH_HEADER);
            } catch (InvalidJwtException | MalformedClaimException | JoseException e) {
                e.printStackTrace();
                try {
                    return onAccessDenied(request, response);
                } catch (IOException ex) {
                    ex.printStackTrace();
                    throw new RuntimeException(ex);
                }
            }
        }

        return true;
    }

    @Override
    public void afterCompletion(ServletRequest request, ServletResponse response, Exception exception) throws Exception {
//        HttpServletRequest servletRequest = (HttpServletRequest) request;
//        HttpServletResponse servletResponse = (HttpServletResponse) response;
//
//        String jwt = servletRequest.getHeader(GLOBAL.TOKEN_INFO.AUTH_HEADER);
//        if(StringUtils.isNotBlank(jwt)){
//            servletResponse.setHeader(GLOBAL.TOKEN_INFO.AUTH_HEADER, JwtUtil.getInstance().reflashJwsToken(jwt));
//            servletResponse.setHeader(GLOBAL.HEADER_INFO.ACCESS_CONTROL_EXPOSE_HEADERS, GLOBAL.TOKEN_INFO.AUTH_HEADER);
//        }
    }

    private boolean onAccessDenied(ServletRequest request, ServletResponse response) throws IOException {
        HttpServletResponse httpResponse = WebUtils.toHttp(response);
        httpResponse.setCharacterEncoding("UTF-8");
        httpResponse.setContentType("application/json;charset=UTF-8");
        httpResponse.setStatus(HttpStatus.UNAUTHORIZED.value());
        PrintWriter writer = httpResponse.getWriter();
        writer.write("{\"errCode\": 401, \"msg\": \"UNAUTHORIZED\"}");
        fillCorsHeader(WebUtils.toHttp(request), httpResponse);
        return false;
    }

    /**
     *
     * @param httpServletRequest
     * @param httpServletResponse
     */
    protected void fillCorsHeader(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) {
        httpServletResponse.setHeader(GLOBAL.HEADER_INFO.ACCESS_CONTROL_ALLOW_ORIGIN, httpServletRequest.getHeader("Origin"));
        httpServletResponse.setHeader(GLOBAL.HEADER_INFO.ACCESS_CONTROL_ALLOW_METHODS, "GET,POST,PUT,PATCH,DELETE,OPTIONS,HEAD");
        httpServletResponse.setHeader(GLOBAL.HEADER_INFO.ACCESS_CONTROL_ALLOW_HEADERS, httpServletRequest.getHeader("Access-Control-Request-Headers"));
        httpServletResponse.setHeader(GLOBAL.HEADER_INFO.ACCESS_CONTROL_EXPOSE_HEADERS, GLOBAL.TOKEN_INFO.AUTH_HEADER);
    }

}
